﻿/*************************************************************************************
 *
 * 文 件 名： Worker
 * 描    述： 从模板新增
 * 
 * 版    本： V1.0
 * 创 建 者： YSW
 * 创建时间： 2022-08-24 8:54:29
 * ======================================
 * 历史更新记录
 * 版本：V          修改时间：         修改人：
 * 修改内容：
 * ======================================
*************************************************************************************/

using CommonModel.Util;
using GXRTBTC.PublicClassLibrary.Model;
using GXRTBTC.PublicClassLibrary.Util;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Newtonsoft.Json;
using System.Net.WebSockets;
using System.Text;

namespace GXRTBTC.WebHisDataService.Controllers
{
    [EnableCors("any")]
    [Route("[controller]")]
    //IgnoreApi = false/true 窗口是否显示到swaggerUI
    [ApiExplorerSettings(IgnoreApi = false)]
    [ApiController]
    public class HisDataController : ControllerBase
    {
        public Worker worker;
        public HisDataController(Worker worker)
        {
            //支持gb2312编码
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

            this.worker = worker;
        }

        /// <summary>
        /// 在这里做一个访问统计记录日志等
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override OkObjectResult Ok([ActionResultObjectValue] object? value)
        {
            return base.Ok(value);
        }

        /// <summary>
        /// 状态监控接口
        /// </summary>
        /// <returns></returns>
        [HttpGet("Status")]
        public OkObjectResult GetStatus()
        {
            return Ok(worker.GetStatus());
        }

        /// <summary>
        /// 历史数据读取接口
        /// </summary>
        /// <param name="positionId"></param>
        /// <param name="beginTime"></param>
        /// <param name="endTime"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        //[HttpGet("DevHis")]
        //public OkObjectResult GetHisData(string positionId, string beginTime, string endTime, int pageIndex, int pageSize)
        //{
        //    return Ok(worker.GetHisData(positionId, beginTime, endTime, pageIndex, pageSize, HttpContext));
        //}

        [HttpPost("DevHis")]
        public OkObjectResult GetHisData()
        {
            CommonDataRes commonDataRes;
            try
            {
                //这里也处理数据
                var len = Convert.ToInt32(HttpContext.Request.ContentLength);
                byte[] buffer = new byte[len];
                string data = "";
                //循坏才能读取所有数据
                var stream = HttpContext.Request.BodyReader.AsStream();
                int bytesRead;
                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    data += Encoding.UTF8.GetString(buffer, 0, bytesRead);
                }

                commonDataRes = worker.GetHisData(data, HttpContext);
            }
            catch (Exception e)
            {
                commonDataRes = new CommonDataRes();
                commonDataRes.Code = WebApiStatusCode.code_5501;
                commonDataRes.Message = e.Message;
            }
            return Ok(commonDataRes);
        }

        /// <summary>
        /// http和websocket一起处理
        /// 使用查询参数
        /// 新协议接口
        /// json接口
        /// 20250411
        /// </summary>
        /// <returns></returns>
        [Route("/data")]
        // AllowAnonymous 属性使“允许未经身份验证的用户访问Login操作”
        //[AllowAnonymous]
        //[HttpPost]
        public async Task<OkObjectResult> GetData()
        {
            return await DataParam();
        }

        /// <summary>
        /// http和websocket一起处理
        /// 使用路径参数
        /// 新协议接口
        /// json接口
        /// 20250411
        /// </summary>
        /// <returns></returns>
        [Route("/data/{apiver}/{level}/{positionid}/{sn}")]
        // AllowAnonymous 属性使“允许未经身份验证的用户访问Login操作”
        //[AllowAnonymous]
        //[HttpPost]
        public async Task<OkObjectResult> GetDataParam()
        {
            return await DataParam();
        }

        /// <summary>
        /// 新协议接口
        /// 数据处理
        /// </summary>
        /// <returns></returns>
        public async Task<OkObjectResult> DataParam()
        {
            //路径参数判断
            WebParamData webParamData = worker.CheckParam(HttpContext);
            WebApiDataFull webApiDataFull = new WebApiDataFull(HttpContext.WebSockets.IsWebSocketRequest) { webParamData = webParamData, CheckParam = false };

            //websocket
            if (HttpContext.WebSockets.IsWebSocketRequest)
            {
                using (var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync())
                {
                    if (!webParamData.nowmal)
                    {
                        WebApiDataResWS ContentRes = new WebApiDataResWS();
                        ContentRes.Type = WebApiTypeCodeWS.error.ToString();
                        ContentRes.Command = WebApiTypeCodeWS.error.ToString();
                        ContentRes.Code = WebApiStatusCode.code_400;
                        ContentRes.Message = EnumHelper.GetDescription(ContentRes.Code) + "，" + webParamData.msg;

                        byte[] responseBuffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ContentRes));
                        await webSocket.SendAsync(new ArraySegment<byte>(responseBuffer), System.Net.WebSockets.WebSocketMessageType.Text, true, CancellationToken.None);
                        await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
                    }
                    else
                    {
                        var wsClient = new WebsocketClient
                        {
                            id = HttpContext.Connection.Id,
                            webSocket = webSocket,
                            positionId = webParamData.positionid
                        };
                        await Receive(wsClient, webApiDataFull);
                    }
                }
            }
            //或者只处理post
            else if (HttpContext.Request.Method.Equals("POST"))
            {
                //HttpContext.Response.StatusCode = 400; // Bad Request if not a WebSocket request

                if (!webParamData.nowmal)
                {
                    WebApiDataRes ContentRes = new WebApiDataRes();
                    ContentRes.Command = WebApiTypeCodeWS.error.ToString();
                    ContentRes.Code = WebApiStatusCode.code_400;
                    ContentRes.Message = EnumHelper.GetDescription(ContentRes.Code) + "，" + webParamData.msg;
                    return Ok(ContentRes);
                }

                //这里也处理数据
                var len = Convert.ToInt32(HttpContext.Request.ContentLength);
                byte[] buffer = new byte[len];
                string data = "";
                //循坏才能读取所有数据
                var stream = HttpContext.Request.BodyReader.AsStream();
                int bytesRead;
                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    data += Encoding.UTF8.GetString(buffer, 0, bytesRead);
                }

                if (worker.CheckData(data.ToString(), webApiDataFull))
                {
                    worker.GetDataJson(webApiDataFull, HttpContext);
                }

                return Ok(webApiDataFull.ContentRes);
            }

            return Ok(new WebApiDataRes() { Code = WebApiStatusCode.code_400, Message = EnumHelper.GetDescription(WebApiStatusCode.code_400), Command = WebApiTypeCodeWS.error.ToString() });
        }

        /// <summary>
        /// 接收消息并处理
        /// </summary>
        /// <param name="context"></param>
        /// <param name="websocketClient"></param>
        /// <returns></returns>
        private async Task Receive(WebsocketClient websocketClient, WebApiDataFull webApiDataFull)
        {
            WebsocketClientManager.websocketClient.Add(websocketClient);
            worker.mLogger.LogInformation("新增连接：" + websocketClient.positionId);

            //封装数组片段：ArraySegment<T> 封装了一个数组及其指定的范围（起始索引和长度），使得可以对数组的某一部分进行操作，而不需要复制数组
            var buffer = new byte[1024 * 4];
            var receiveResult = await websocketClient.webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            while (!receiveResult.CloseStatus.HasValue)
            {
                //string msgString = Encoding.UTF8.GetString(buffer);
                //这行中文会乱码
                //string msgString = Encoding.GetEncoding(TransForm.encode).GetString(buffer, 0, receiveResult.Count);
                string data = Encoding.UTF8.GetString(buffer, 0, receiveResult.Count);
                worker.CheckData(data.ToString(), webApiDataFull);


                //心跳包记录时间
                if (((WebApiDataResWS)webApiDataFull.ContentRes).Type.Equals(WebApiTypeCodeWS.heartbeat.ToString()))
                {
                    WebsocketClientManager.websocketClient.SetTime(HttpContext.Connection.Id);
                }
                //授权处理
                else if (((WebApiDataResWS)webApiDataFull.ContentRes).Type.Equals(WebApiTypeCodeWS.auth.ToString()))
                {
                    WebsocketClientManager.websocketClient.SetAuth(HttpContext.Connection.Id, worker.GetValidToken(webApiDataFull.ContentReq));
                }

                //worker.mLogger.LogInformation($"收到来自{websocketClient.positionId}的数据ContentReq=" + webApiDataFull.ContentReq.RequestId + " ContentRes=" + webApiDataFull.ContentRes.RequestId);
                //异步等待，判断并设置结果
                TaskCompletionSource<Object> tcs = TcsTimeoutHelper.tcsManager.GetTcs(webApiDataFull.ContentRes.RequestId);
                if (tcs != null)
                {
                    try
                    {
                        worker.mLogger.LogInformation("操作返回，RequestId=" + webApiDataFull.ContentRes.RequestId);
                        tcs.TrySetResult(JsonConvert.DeserializeObject<WebApiDataResWS>(data));
                    }
                    catch (Exception ex)
                    {
                        ((WebApiDataResWS)webApiDataFull.ContentRes).Message += EnumHelper.GetDescription(((WebApiDataResWS)webApiDataFull.ContentRes).Code) + "，返回结果：" + ((WebApiDataResWS)webApiDataFull.ContentRes).Code + "，但返回数据解析异常";
                        ((WebApiDataResWS)webApiDataFull.ContentRes).Code = WebApiStatusCode.code_5504;
                        tcs.TrySetResult(webApiDataFull.ContentRes);
                        worker.mLogger.LogError("操作返回处理异常，RequestId=" + webApiDataFull.ContentRes.RequestId + " data:" + data + " Eror:" + ex.Message);
                    }
                }
                //根据是否鉴权，分开处理
                else if (WebsocketClientManager.websocketClient.GetAuth(HttpContext.Connection.Id))
                {
                    //关闭连接
                    if (((WebApiDataResWS)webApiDataFull.ContentRes).Type.Equals(WebApiTypeCodeWS.close.ToString()))
                    {
                        break;
                    }
                    //错误
                    else if (((WebApiDataResWS)webApiDataFull.ContentRes).Type.Equals(WebApiTypeCodeWS.error.ToString()))
                    {
                        worker.mLogger.LogError(worker.GetClientIp(HttpContext) + " webSocket发生异常，ConnectionId=" + HttpContext.Connection.Id);
                        ((WebApiDataResWS)webApiDataFull.ContentRes).Message = "发生异常：" + ((WebApiDataResWS)webApiDataFull.ContentRes).Message;
                    }
                    //数据
                    else if (((WebApiDataResWS)webApiDataFull.ContentRes).Type.Equals(WebApiTypeCodeWS.data.ToString()))
                    {
                        worker.GetDataJson(webApiDataFull, HttpContext);
                    }
                    //心跳包返回
                    else if (((WebApiDataResWS)webApiDataFull.ContentRes).Type.Equals(WebApiTypeCodeWS.heartbeat.ToString()))
                    {
                        ((WebApiDataResWS)webApiDataFull.ContentRes).Command = "heartbeat_ack";
                        ((WebApiDataResWS)webApiDataFull.ContentRes).Message = "心跳消息";
                    }
                    //未知
                    else
                    {
                        ((WebApiDataResWS)webApiDataFull.ContentRes).Code = WebApiStatusCode.code_404;
                        ((WebApiDataResWS)webApiDataFull.ContentRes).Message = EnumHelper.GetDescription(((WebApiDataResWS)webApiDataFull.ContentRes).Code) + "，请检查Type参数（" + ((WebApiDataResWS)webApiDataFull.ContentRes).Type + "）";
                        ((WebApiDataResWS)webApiDataFull.ContentRes).Type = WebApiTypeCodeWS.error.ToString();
                    }

                    byte[] responseBuffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(webApiDataFull.ContentRes));
                    await websocketClient.webSocket.SendAsync(new ArraySegment<byte>(responseBuffer), receiveResult.MessageType, receiveResult.EndOfMessage, CancellationToken.None);
                }
                else
                {
                    //未授权的返回处理
                    ((WebApiDataResWS)webApiDataFull.ContentRes).Type = WebApiTypeCodeWS.error.ToString();
                    ((WebApiDataResWS)webApiDataFull.ContentRes).Code = WebApiStatusCode.code_401;
                    ((WebApiDataResWS)webApiDataFull.ContentRes).Message = EnumHelper.GetDescription(((WebApiDataResWS)webApiDataFull.ContentRes).Code);

                    byte[] responseBuffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(webApiDataFull.ContentRes));
                    await websocketClient.webSocket.SendAsync(new ArraySegment<byte>(responseBuffer), receiveResult.MessageType, receiveResult.EndOfMessage, CancellationToken.None);
                }

                receiveResult = await websocketClient.webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            }

            WebsocketClientManager.websocketClient.Remove(websocketClient);
            worker.mLogger.LogError(worker.GetClientIp(HttpContext) + " webSocket关闭，ConnectionId=" + HttpContext.Connection.Id);
            await websocketClient.webSocket.CloseAsync(receiveResult.CloseStatus.Value, receiveResult.CloseStatusDescription, CancellationToken.None);
        }

        /// <summary>
        /// 这是get方法
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public string Get()
        {
            return "连接正常";
        }
    }
}
